﻿Components.utils.import('resource://app/jsmodules/StringUtils.jsm');


// Make a namespace.
if (typeof GrowlgntpSongbird == 'undefined') {
    var GrowlgntpSongbird = {};
}


/**
 * UI controller that is loaded into the main player window
 */
GrowlgntpSongbird.Controller = {

	APPNAME : "Songbird",

	growl : Components.classes['@growlforwindows.com/growlgntp;1'].getService().wrappedJSObject,

	// Called when the window finishes loading
	onLoad: function() {
		// initialization code
		this._initialized = true;
		this._isPaused = false;

		// Perform extra actions the first time the extension is run
		var firstrun = true;
		try {
			this._prefs = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces.nsIPrefService).getBranch('');
			firstrun = this._prefs.getBoolPref('extensions.growlgntp-songbird.firstrun');
		}
		catch(err) {
			this._prefs = NULL;
			Components.utils.reportError('Growl/GNTP ERROR: ' + err.toString());
		}
		
		if (firstrun) {
			if (this._prefs)
				this._prefs.setBoolPref('extensions.growlgntp-songbird.firstrun', false);
			this._firstRunSetup();
		}

		if (!this.growl.isInitialized) {
			this.growl.init();

			var gMM = Components.classes['@songbirdnest.com/Songbird/Mediacore/Manager;1'].getService(Components.interfaces.sbIMediacoreManager);
			gMM.addListener(this.myListener);

			var gLM = Components.classes['@songbirdnest.com/Songbird/library/Manager;1'].getService(Components.interfaces.sbILibraryManager); 
			gLM.addListener(this.myListener);
		}

		// Get folder with cover images (artwork)
		this._artworkFolder = Components.classes['@mozilla.org/file/directory_service;1'].getService(Components.interfaces.nsIProperties).get('ProfLD', Components.interfaces.nsIFile).path;
		this._artworkFolder += '/artwork';

		// Get localized strings
		this._localize = new SBStringBundle('chrome://growlgntp-songbird/locale/overlay.properties');

		this.register();
		this.growl.addClickCallbackHandler(this.clickCallbackHandler);
	},

	// Called when the window is about to close
	onUnLoad: function() {
		this._initialized = false;
		this._isPaused = false;
	},

	// Perform extra setup the first time the extension is run
	_firstRunSetup : function() {
	},

	// Register the notification types and the application icon
	register : function() {
		try {
			// Get the icon
			var id = 'growlgntp-songbird@brian.dunnington';
			var extension = Components.classes['@mozilla.org/extensions/manager;1'].getService(Components.interfaces.nsIExtensionManager).getInstallLocation(id).getItemLocation(id);

			var icon = extension.path + '\\chrome\\skin\\';
			switch (this._prefs ? this._prefs.getIntPref('extensions.growlgntp-songbird.icon') : 0)
			{
			case 1:
				icon += 'songbird-yellow.png';
				break;
			default:
				icon += 'songbird.png';
				break;
			}

			// Register notifications
			var ntTrackChange = {Name: 'trackchange', DisplayName: this._localize.get('growl.notify.TrackChange')};
			var ntTrackPaused = {Name: 'trackpaused', DisplayName: this._localize.get('growl.notify.TrackPausedResumed')};
			var ntEndOfSequence = {Name: 'endofsequence', DisplayName: this._localize.get('growl.notify.EndOfSequence')};
			var ntLibConnected = {Name: 'libconnected', DisplayName: this._localize.get('growl.notify.LibConnected')};
			var ntLibRemoved = {Name: 'libremoved', DisplayName: this._localize.get('growl.notify.LibRemoved')};

			var notificationTypes = [ntTrackChange, ntTrackPaused, ntEndOfSequence, ntLibConnected, ntLibRemoved];
			this.growl.register(GrowlgntpSongbird.Controller.APPNAME, icon, notificationTypes);
		}
		catch(err) {
			Components.utils.reportError('Growl/GNTP ERROR: ' + err.toString());
		}
	},

	// Send notifications via GROWL/GNTP
	doNotification : function(type, title, message, callbackContext, callbackType, image) {
		this.register();
		if (title == '')
			title = '.';	// avoid empty title -> notification is not displayed then!!! 
		this.growl.notify(GrowlgntpSongbird.Controller.APPNAME, type, title, message, callbackContext, callbackType, image);
	},

	// Handle callback if user clicked on notify window
	clickCallbackHandler : function(data) {
		var restoreWindow = true;

		if (data.type == 'trackchange') {
			var gMM = Components.classes['@songbirdnest.com/Songbird/Mediacore/Manager;1'].getService(Components.interfaces.sbIMediacoreManager);
			gMM.sequencer.next();
			restoreWindow = false;
		}

		if (restoreWindow) {
			var windowMediator = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(Components.interfaces.nsIWindowMediator);
			var recentWindow = windowMediator.getMostRecentWindow('Songbird:Main');
			if (recentWindow)
				recentWindow.focus();
		}
	},

	// Get file path and name for the current media item artwork
	getImageFilePath : function(mediaItem) {
		var imageFilePath = mediaItem.getProperty(SBProperties.primaryImageURL);
		var uri = null;
		
		if (imageFilePath != null) {
			try	{
				var ioService = Components.classes['@mozilla.org/network/io-service;1'].getService(Components.interfaces.nsIIOService);
				uri = ioService.newURI(imageFilePath, null, null);
			}
			catch (err) {
				Components.utils.reportError('Growl/GNTP ERROR: ' + err.toString());
				return '';
			}
		}
		if (!uri)
			return '';

		switch (uri.scheme)
		{
		case 'file':
			var fph = ioService.getProtocolHandler('file').QueryInterface(Components.interfaces.nsIFileProtocolHandler);
			var imageFile = fph.getFileFromURLSpec(imageFilePath);
			imageFilePath = imageFile.path;
			break;

		case 'resource':    // resource://sb-artwork/xxxxx.jpg
			imageFilePath = imageFilePath.replace(/resource:\/\/sb-artwork/, this._artworkFolder);
			break;

		case 'http':
			break;

		case 'chrome':		// chrome://songbird/skin/album-art/default-cover.png
			Components.utils.reportError('Growl/GNTP WARNING: Album art has "chrome" uri!');
			imageFilePath = '';
			break;

		default:
			Components.utils.reportError('Growl/GNTP WARNING: Album art has unrecognized uri; ' + uri);
			imageFilePath = '';
			break;
		}

		return imageFilePath;
	},

	// Parse text and replace place holders with media item properties
	parseVariables : function(text, mediaItem) {
		text = text.replace(/%NL%/gi, '\n');
		if (mediaItem == null)
			return text;

		if (text.search(/%ALBUM%/i) != -1) {
			var content = mediaItem.getProperty(SBProperties.albumName);
			text = text.replace(/%ALBUM%/gi, content==null ? '' : content);
		}
		if (text.search(/%ARTIST%/i) != -1) {
			var content = mediaItem.getProperty(SBProperties.artistName);
			text = text.replace(/%ARTIST%/gi, content==null ? '' : content);
		}
		if (text.search(/%DISCNUM%/i) != -1) {
			var content = mediaItem.getProperty(SBProperties.discNumber);
			text = text.replace(/%DISCNUM%/gi, content==null ? '' : content);
		}
		if (text.search(/%DISCS%/i) != -1) {
			var content = mediaItem.getProperty(SBProperties.totalDiscs);
			text = text.replace(/%DISCS%/gi, content==null ? '' : content);
		}
		if (text.search(/%DURATION%/i) != -1) {
			var duration = parseInt(mediaItem.getProperty(SBProperties.duration) / 1000000);
			var minutes = parseInt(duration / 60);
			var seconds = parseInt(duration % 60);
			if (seconds < 10)
				seconds = '0' + seconds;
			var str = minutes +':'+ seconds;
			text = text.replace(/%DURATION%/gi, str);
		}
		if (text.search(/%GENRE%/i) != -1) {
			var content = mediaItem.getProperty(SBProperties.genre);
			text = text.replace(/%GENRE%/gi, content==null ? '' : content);
		}
		if (text.search(/%RATING%/i) != -1) {
			var content = mediaItem.getProperty(SBProperties.rating);
			text = text.replace(/%RATING%/gi, content==null ? parseInt(content) : 0);
		}
		if (text.search(/%RATING_STARS%/i) != -1) {
			var rating = parseInt(mediaItem.getProperty(SBProperties.rating));
			var unicode = true;
			if (this._prefs)
				unicode = this._prefs.getBoolPref('extensions.growlgntp-songbird.unicode-stars');

			var content = '';
			if (unicode) {
				for (var i = 1; i <= 5; i++) {
					if (i <= rating)
						content += '\u2605';	// black star
					else
						content += '\u2606';	// white star
				}
			}
			else {
				for (var i = 1; i <= rating; i++) {
					if (strlen(content))
						content += ' ';
					content += '*';
				}
			}
			text = text.replace(/%RATING_STARS%/gi, content);
		}
		if (text.search(/%TITLE%/i) != -1) {
			var content = mediaItem.getProperty(SBProperties.trackName);
			text = text.replace(/%TITLE%/gi, content==null ? '' : content);
		}
		if (text.search(/%TRACKNUM%/i) != -1) {
			var content = mediaItem.getProperty(SBProperties.trackNumber);
			text = text.replace(/%TRACKNUM%/gi, content==null ? '' : content);
		}
		if (text.search(/%TRACKS%/i) != -1) {
			var content = mediaItem.getProperty(SBProperties.totalTracks);
			text = text.replace(/%TRACKS%/gi, content==null ? '' : content);
		}
		if (text.search(/%YEAR%/i) != -1) {
			var content = mediaItem.getProperty(SBProperties.year);
			text = text.replace(/%YEAR%/gi, content==null ? '' : content);
		}
		return text;
	},

	// Listen and handle events to display notifications
	myListener :
	{  
		onMediacoreEvent : function(ev) {
			switch (ev.type)
			{
			// New track has been started to be played
			case Components.interfaces.sbIMediacoreEvent.TRACK_CHANGE:
				var mediaItem = ev.data;
				GrowlgntpSongbird.Controller._isPaused = false;
				
				var titleFormat = '%TITLE%';
				var messageFormat = '%ARTIST%%NL%%ALBUM%';
				if (GrowlgntpSongbird.Controller._prefs) {
					titleFormat = GrowlgntpSongbird.Controller._prefs.getCharPref('extensions.growlgntp-songbird.trackchange-title');
					messageFormat = GrowlgntpSongbird.Controller._prefs.getCharPref('extensions.growlgntp-songbird.trackchange-message');
				}

				var title = GrowlgntpSongbird.Controller.parseVariables(titleFormat, mediaItem);
				var message = GrowlgntpSongbird.Controller.parseVariables(messageFormat, mediaItem);
				var image = GrowlgntpSongbird.Controller.getImageFilePath(mediaItem);
				GrowlgntpSongbird.Controller.doNotification('trackchange', title, message, mediaItem.guid, 'trackchange', image);
				break;

			// Playback paused by user
			case Components.interfaces.sbIMediacoreEvent.STREAM_PAUSE:
				GrowlgntpSongbird.Controller._isPaused = true;
				var title = GrowlgntpSongbird.Controller._localize.get('growl.notify.TrackPaused');
				var message = GrowlgntpSongbird.Controller._localize.get('growl.notify.TrackPausedMsg');
				GrowlgntpSongbird.Controller.doNotification('trackpaused', title, message, 'trackPaused', 'trackpaused', null);
				break;

			// Playback started by user (after pause)
			case Components.interfaces.sbIMediacoreEvent.STREAM_START:
				if (GrowlgntpSongbird.Controller._isPaused) {
					GrowlgntpSongbird.Controller._isPaused = false;
					var title = GrowlgntpSongbird.Controller._localize.get('growl.notify.TrackResumed');
					var message = GrowlgntpSongbird.Controller._localize.get('growl.notify.TrackResumedMsg');
					var guid = 'trackResumed';
					var image = null;
					
					if (GrowlgntpSongbird.Controller._prefs && GrowlgntpSongbird.Controller._prefs.getBoolPref('extensions.growlgntp-songbird.resume-customized')) {
						var gMM = Components.classes['@songbirdnest.com/Songbird/Mediacore/Manager;1'].getService(Components.interfaces.sbIMediacoreManager);
						var mediaItem = gMM.sequencer.currentItem;
						if (mediaItem != null) {
							var titleFormat = GrowlgntpSongbird.Controller._prefs.getCharPref('extensions.growlgntp-songbird.resume-title');
							var messageFormat = GrowlgntpSongbird.Controller._prefs.getCharPref('extensions.growlgntp-songbird.resume-message');
	
							title = GrowlgntpSongbird.Controller.parseVariables(titleFormat, mediaItem);
							message = GrowlgntpSongbird.Controller.parseVariables(messageFormat, mediaItem);
							guid = mediaItem.guid;
							image = GrowlgntpSongbird.Controller.getImageFilePath(mediaItem);
						}
						else {
							Components.utils.reportError('Growl/GNTP WARNING: Media item not found on resuming track');
						}
					}
					GrowlgntpSongbird.Controller.doNotification('trackpaused', title, message, guid, 'trackpaused', image);
				}
				break;

			// Playback stopped due to no more items in sequence/play list
			case Components.interfaces.sbIMediacoreEvent.SEQUENCE_END:
				var title = GrowlgntpSongbird.Controller._localize.get('growl.notify.EndOfSequence');
				var message = GrowlgntpSongbird.Controller._localize.get('growl.notify.EndOfSequenceMsg');
				GrowlgntpSongbird.Controller.doNotification('endofsequence', title, message, 'EndOfSequence', 'endofsequence', null);
				break;
			} 
		},

		// Library has been registered (mp3 player has been plugged in)
		onLibraryRegistered : function(library) {
			var title = GrowlgntpSongbird.Controller._localize.get('growl.notify.LibConnected');
			var message = GrowlgntpSongbird.Controller._localize.formatCountString('growl.notify.LibConnected', 1, [library.device.name], library.device.name);
			GrowlgntpSongbird.Controller.doNotification('libconnected', title, message, library.device.id, 'libconnected', null);
		},

		// Library has been unregistered (mp3 player has been unplugged)
		onLibraryUnregistered : function(library) {
			var title = GrowlgntpSongbird.Controller._localize.get('growl.notify.LibRemoved');
			var message = GrowlgntpSongbird.Controller._localize.formatCountString('growl.notify.LibRemoved', 1, [library.device.name], library.device.name);
			GrowlgntpSongbird.Controller.doNotification('libremoved', title, message, library.device.id, 'libremoved', null);
		}
	},

	sendTest : function() {
		doNotification('_test_', 'Growl Test', 'This is a test notification from Songbird');
	}
};

window.addEventListener('load', function(e) { GrowlgntpSongbird.Controller.onLoad(e); }, false);
window.addEventListener('unload', function(e) { GrowlgntpSongbird.Controller.onUnLoad(e); }, false);
dump('growlgntp-songbird is loading');